home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 22 / PCPP #22.iso / Quake2 / q2source_12_11 / utils3 / bsp / qbsp3 / qbsp3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-19  |  10.2 KB  |  518 lines

  1. // csg4.c
  2.  
  3. #include "qbsp.h"
  4.  
  5. extern    float subdivide_size;
  6.  
  7. char        source[1024];
  8. char        name[1024];
  9.  
  10. vec_t        microvolume = 1.0;
  11. qboolean    noprune;
  12. qboolean    glview;
  13. qboolean    nodetail;
  14. qboolean    fulldetail;
  15. qboolean    onlyents;
  16. qboolean    nomerge;
  17. qboolean    nowater;
  18. qboolean    nofill;
  19. qboolean    nocsg;
  20. qboolean    noweld;
  21. qboolean    noshare;
  22. qboolean    nosubdiv;
  23. qboolean    notjunc;
  24. qboolean    noopt;
  25. qboolean    leaktest;
  26. qboolean    verboseentities;
  27.  
  28. char        outbase[32];
  29.  
  30. int            block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
  31.  
  32. int            entity_num;
  33.  
  34.  
  35. node_t        *block_nodes[10][10];
  36.  
  37. /*
  38. ============
  39. BlockTree
  40.  
  41. ============
  42. */
  43. node_t    *BlockTree (int xl, int yl, int xh, int yh)
  44. {
  45.     node_t    *node;
  46.     vec3_t    normal;
  47.     float    dist;
  48.     int        mid;
  49.  
  50.     if (xl == xh && yl == yh)
  51.     {
  52.         node = block_nodes[xl+5][yl+5];
  53.         if (!node)
  54.         {    // return an empty leaf
  55.             node = AllocNode ();
  56.             node->planenum = PLANENUM_LEAF;
  57.             node->contents = 0; //CONTENTS_SOLID;
  58.             return node;
  59.         }
  60.         return node;
  61.     }
  62.  
  63.     // create a seperator along the largest axis
  64.     node = AllocNode ();
  65.  
  66.     if (xh - xl > yh - yl)
  67.     {    // split x axis
  68.         mid = xl + (xh-xl)/2 + 1;
  69.         normal[0] = 1;
  70.         normal[1] = 0;
  71.         normal[2] = 0;
  72.         dist = mid*1024;
  73.         node->planenum = FindFloatPlane (normal, dist);
  74.         node->children[0] = BlockTree ( mid, yl, xh, yh);
  75.         node->children[1] = BlockTree ( xl, yl, mid-1, yh);
  76.     }
  77.     else
  78.     {
  79.         mid = yl + (yh-yl)/2 + 1;
  80.         normal[0] = 0;
  81.         normal[1] = 1;
  82.         normal[2] = 0;
  83.         dist = mid*1024;
  84.         node->planenum = FindFloatPlane (normal, dist);
  85.         node->children[0] = BlockTree ( xl, mid, xh, yh);
  86.         node->children[1] = BlockTree ( xl, yl, xh, mid-1);
  87.     }
  88.  
  89.     return node;
  90. }
  91.  
  92. /*
  93. ============
  94. ProcessBlock_Thread
  95.  
  96. ============
  97. */
  98. int            brush_start, brush_end;
  99. void ProcessBlock_Thread (int blocknum)
  100. {
  101.     int        xblock, yblock;
  102.     vec3_t        mins, maxs;
  103.     bspbrush_t    *brushes;
  104.     tree_t        *tree;
  105.     node_t        *node;
  106.  
  107.     yblock = block_yl + blocknum / (block_xh-block_xl+1);
  108.     xblock = block_xl + blocknum % (block_xh-block_xl+1);
  109.  
  110.     qprintf ("############### block %2i,%2i ###############\n", xblock, yblock);
  111.  
  112.     mins[0] = xblock*1024;
  113.     mins[1] = yblock*1024;
  114.     mins[2] = -4096;
  115.     maxs[0] = (xblock+1)*1024;
  116.     maxs[1] = (yblock+1)*1024;
  117.     maxs[2] = 4096;
  118.  
  119.     // the makelist and chopbrushes could be cached between the passes...
  120.     brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);
  121.     if (!brushes)
  122.     {
  123.         node = AllocNode ();
  124.         node->planenum = PLANENUM_LEAF;
  125.         node->contents = CONTENTS_SOLID;
  126.         block_nodes[xblock+5][yblock+5] = node;
  127.         return;
  128.     }
  129.  
  130.     if (!nocsg)
  131.         brushes = ChopBrushes (brushes);
  132.  
  133.     tree = BrushBSP (brushes, mins, maxs);
  134.  
  135.     block_nodes[xblock+5][yblock+5] = tree->headnode;
  136. }
  137.  
  138. /*
  139. ============
  140. ProcessWorldModel
  141.  
  142. ============
  143. */
  144. void ProcessWorldModel (void)
  145. {
  146.     entity_t    *e;
  147.     tree_t        *tree;
  148.     qboolean    leaked;
  149.     qboolean    optimize;
  150.  
  151.     e = &entities[entity_num];
  152.  
  153.     brush_start = e->firstbrush;
  154.     brush_end = brush_start + e->numbrushes;
  155.     leaked = false;
  156.  
  157.     //
  158.     // perform per-block operations
  159.     //
  160.     if (block_xh * 1024 > map_maxs[0])
  161.         block_xh = floor(map_maxs[0]/1024.0);
  162.     if ( (block_xl+1) * 1024 < map_mins[0])
  163.         block_xl = floor(map_mins[0]/1024.0);
  164.     if (block_yh * 1024 > map_maxs[1])
  165.         block_yh = floor(map_maxs[1]/1024.0);
  166.     if ( (block_yl+1) * 1024 < map_mins[1])
  167.         block_yl = floor(map_mins[1]/1024.0);
  168.  
  169.     if (block_xl <-4)
  170.         block_xl = -4;
  171.     if (block_yl <-4)
  172.         block_yl = -4;
  173.     if (block_xh > 3)
  174.         block_xh = 3;
  175.     if (block_yh > 3)
  176.         block_yh = 3;
  177.  
  178.     for (optimize = false ; optimize <= true ; optimize++)
  179.     {
  180.         qprintf ("--------------------------------------------\n");
  181.  
  182.         RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),
  183.             !verbose, ProcessBlock_Thread);
  184.  
  185.         //
  186.         // build the division tree
  187.         // oversizing the blocks guarantees that all the boundaries
  188.         // will also get nodes.
  189.         //
  190.  
  191.         qprintf ("--------------------------------------------\n");
  192.  
  193.         tree = AllocTree ();
  194.         tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);
  195.  
  196.         tree->mins[0] = (block_xl)*1024;
  197.         tree->mins[1] = (block_yl)*1024;
  198.         tree->mins[2] = map_mins[2] - 8;
  199.  
  200.         tree->maxs[0] = (block_xh+1)*1024;
  201.         tree->maxs[1] = (block_yh+1)*1024;
  202.         tree->maxs[2] = map_maxs[2] + 8;
  203.  
  204.         //
  205.         // perform the global operations
  206.         //
  207.         MakeTreePortals (tree);
  208.  
  209.         if (FloodEntities (tree))
  210.             FillOutside (tree->headnode);
  211.         else
  212.         {
  213.             printf ("**** leaked ****\n");
  214.             leaked = true;
  215.             LeakFile (tree);
  216.             if (leaktest)
  217.             {
  218.                 printf ("--- MAP LEAKED ---\n");
  219.                 exit (0);
  220.             }
  221.         }
  222.  
  223.         MarkVisibleSides (tree, brush_start, brush_end);
  224.         if (noopt || leaked)
  225.             break;
  226.         if (!optimize)
  227.         {
  228.             FreeTree (tree);
  229.         }
  230.     }
  231.  
  232.     FloodAreas (tree);
  233.     if (glview)
  234.         WriteGLView (tree, source);
  235.     MakeFaces (tree->headnode);
  236.     FixTjuncs (tree->headnode);
  237.  
  238.     if (!noprune)
  239.         PruneNodes (tree->headnode);
  240.  
  241.     WriteBSP (tree->headnode);
  242.  
  243.     if (!leaked)
  244.         WritePortalFile (tree);
  245.  
  246.     FreeTree (tree);
  247. }
  248.  
  249. /*
  250. ============
  251. ProcessSubModel
  252.  
  253. ============
  254. */
  255. void ProcessSubModel (void)
  256. {
  257.     entity_t    *e;
  258.     int            start, end;
  259.     tree_t        *tree;
  260.     bspbrush_t    *list;
  261.     vec3_t        mins, maxs;
  262.  
  263.     e = &entities[entity_num];
  264.  
  265.     start = e->firstbrush;
  266.     end = start + e->numbrushes;
  267.  
  268.     mins[0] = mins[1] = mins[2] = -4096;
  269.     maxs[0] = maxs[1] = maxs[2] = 4096;
  270.     list = MakeBspBrushList (start, end, mins, maxs);
  271.     if (!nocsg)
  272.         list = ChopBrushes (list);
  273.     tree = BrushBSP (list, mins, maxs);
  274.     MakeTreePortals (tree);
  275.     MarkVisibleSides (tree, start, end);
  276.     MakeFaces (tree->headnode);
  277.     FixTjuncs (tree->headnode);
  278.     WriteBSP (tree->headnode);
  279.     FreeTree (tree);
  280. }
  281.  
  282. /*
  283. ============
  284. ProcessModels
  285. ============
  286. */
  287. void ProcessModels (void)
  288. {
  289.     BeginBSPFile ();
  290.  
  291.     for (entity_num=0 ; entity_num< num_entities ; entity_num++)
  292.     {
  293.         if (!entities[entity_num].numbrushes)
  294.             continue;
  295.  
  296.         qprintf ("############### model %i ###############\n", nummodels);
  297.         BeginModel ();
  298.         if (entity_num == 0)
  299.             ProcessWorldModel ();
  300.         else
  301.             ProcessSubModel ();
  302.         EndModel ();
  303.  
  304.         if (!verboseentities)
  305.             verbose = false;    // don't bother printing submodels
  306.     }
  307.  
  308.     EndBSPFile ();
  309. }
  310.  
  311.  
  312. /*
  313. ============
  314. main
  315. ============
  316. */
  317. int main (int argc, char **argv)
  318. {
  319.     int        i;
  320.     double        start, end;
  321.     char        path[1024];
  322.  
  323.     printf ("---- qbsp3 ----\n");
  324.  
  325.     for (i=1 ; i<argc ; i++)
  326.     {
  327.         if (!strcmp(argv[i],"-threads"))
  328.         {
  329.             numthreads = atoi (argv[i+1]);
  330.             i++;
  331.         }
  332.         else if (!strcmp(argv[i],"-glview"))
  333.         {
  334.             glview = true;
  335.         }
  336.         else if (!strcmp(argv[i], "-v"))
  337.         {
  338.             printf ("verbose = true\n");
  339.             verbose = true;
  340.         }
  341.         else if (!strcmp(argv[i], "-draw"))
  342.         {
  343.             printf ("drawflag = true\n");
  344.             drawflag = true;
  345.         }
  346.         else if (!strcmp(argv[i], "-noweld"))
  347.         {
  348.             printf ("noweld = true\n");
  349.             noweld = true;
  350.         }
  351.         else if (!strcmp(argv[i], "-nocsg"))
  352.         {
  353.             printf ("nocsg = true\n");
  354.             nocsg = true;
  355.         }
  356.         else if (!strcmp(argv[i], "-noshare"))
  357.         {
  358.             printf ("noshare = true\n");
  359.             noshare = true;
  360.         }
  361.         else if (!strcmp(argv[i], "-notjunc"))
  362.         {
  363.             printf ("notjunc = true\n");
  364.             notjunc = true;
  365.         }
  366.         else if (!strcmp(argv[i], "-nowater"))
  367.         {
  368.             printf ("nowater = true\n");
  369.             nowater = true;
  370.         }
  371.         else if (!strcmp(argv[i], "-noopt"))
  372.         {
  373.             printf ("noopt = true\n");
  374.             noopt = true;
  375.         }
  376.         else if (!strcmp(argv[i], "-noprune"))
  377.         {
  378.             printf ("noprune = true\n");
  379.             noprune = true;
  380.         }
  381.         else if (!strcmp(argv[i], "-nofill"))
  382.         {
  383.             printf ("nofill = true\n");
  384.             nofill = true;
  385.         }
  386.         else if (!strcmp(argv[i], "-nomerge"))
  387.         {
  388.             printf ("nomerge = true\n");
  389.             nomerge = true;
  390.         }
  391.         else if (!strcmp(argv[i], "-nosubdiv"))
  392.         {
  393.             printf ("nosubdiv = true\n");
  394.             nosubdiv = true;
  395.         }
  396.         else if (!strcmp(argv[i], "-nodetail"))
  397.         {
  398.             printf ("nodetail = true\n");
  399.             nodetail = true;
  400.         }
  401.         else if (!strcmp(argv[i], "-fulldetail"))
  402.         {
  403.             printf ("fulldetail = true\n");
  404.             fulldetail = true;
  405.         }
  406.         else if (!strcmp(argv[i], "-onlyents"))
  407.         {
  408.             printf ("onlyents = true\n");
  409.             onlyents = true;
  410.         }
  411.         else if (!strcmp(argv[i], "-micro"))
  412.         {
  413.             microvolume = atof(argv[i+1]);
  414.             printf ("microvolume = %f\n", microvolume);
  415.             i++;
  416.         }
  417.         else if (!strcmp(argv[i], "-leaktest"))
  418.         {
  419.             printf ("leaktest = true\n");
  420.             leaktest = true;
  421.         }
  422.         else if (!strcmp(argv[i], "-verboseentities"))
  423.         {
  424.             printf ("verboseentities = true\n");
  425.             verboseentities = true;
  426.         }
  427.         else if (!strcmp(argv[i], "-chop"))
  428.         {
  429.             subdivide_size = atof(argv[i+1]);
  430.             printf ("subdivide_size = %f\n", subdivide_size);
  431.             i++;
  432.         }
  433.         else if (!strcmp(argv[i], "-block"))
  434.         {
  435.             block_xl = block_xh = atoi(argv[i+1]);
  436.             block_yl = block_yh = atoi(argv[i+2]);
  437.             printf ("block: %i,%i\n", block_xl, block_yl);
  438.             i+=2;
  439.         }
  440.         else if (!strcmp(argv[i], "-blocks"))
  441.         {
  442.             block_xl = atoi(argv[i+1]);
  443.             block_yl = atoi(argv[i+2]);
  444.             block_xh = atoi(argv[i+3]);
  445.             block_yh = atoi(argv[i+4]);
  446.             printf ("blocks: %i,%i to %i,%i\n", 
  447.                 block_xl, block_yl, block_xh, block_yh);
  448.             i+=4;
  449.         }
  450.         else if (!strcmp (argv[i],"-tmpout"))
  451.         {
  452.             strcpy (outbase, "/tmp");
  453.         }
  454.         else if (argv[i][0] == '-')
  455.             Error ("Unknown option \"%s\"", argv[i]);
  456.         else
  457.             break;
  458.     }
  459.  
  460.     if (i != argc - 1)
  461.         Error ("usage: qbsp3 [options] mapfile");
  462.  
  463.     start = I_FloatTime ();
  464.  
  465.     ThreadSetDefault ();
  466. numthreads = 1;        // multiple threads aren't helping...
  467.     SetQdirFromPath (argv[i]);
  468.  
  469.     strcpy (source, ExpandArg (argv[i]));
  470.     StripExtension (source);
  471.  
  472.     // delete portal and line files
  473.     sprintf (path, "%s.prt", source);
  474.     remove (path);
  475.     sprintf (path, "%s.lin", source);
  476.     remove (path);
  477.  
  478.     strcpy (name, ExpandArg (argv[i]));    
  479.     DefaultExtension (name, ".map");    // might be .reg
  480.  
  481.     //
  482.     // if onlyents, just grab the entites and resave
  483.     //
  484.     if (onlyents)
  485.     {
  486.         char out[1024];
  487.  
  488.         sprintf (out, "%s.bsp", source);
  489.         LoadBSPFile (out);
  490.         num_entities = 0;
  491.  
  492.         LoadMapFile (name);
  493.         SetModelNumbers ();
  494.         SetLightStyles ();
  495.  
  496.         UnparseEntities ();
  497.  
  498.         WriteBSPFile (out);
  499.     }
  500.     else
  501.     {
  502.         //
  503.         // start from scratch
  504.         //
  505.         LoadMapFile (name);
  506.         SetModelNumbers ();
  507.         SetLightStyles ();
  508.  
  509.         ProcessModels ();
  510.     }
  511.  
  512.     end = I_FloatTime ();
  513.     printf ("%5.0f seconds elapsed\n", end-start);
  514.  
  515.     return 0;
  516. }
  517.  
  518.